import re
# from urllib import request

from django import http
from django.contrib.auth import login, authenticate, logout
from django.http import JsonResponse
from django.shortcuts import render
import json
# Create your views here.
from django.views import View
from django_redis import get_redis_connection
from redis import Redis

from apps.users.models import User
from apps.users.utils import generate_verify_email_url, check_verify_email_token
from celery_tasks.email.tasks import send_email_active
from utils.views import LoginRequiredJSONMixin


class UsernameCountView(View):

    def get(self, request, username):
        # - 1 接收 用户名
        print(username)

        #   - 2 根据用户名查询数据库，查询数量有几个
        try:
            count = User.objects.filter(username=username).count()
        except Exception as e:
            print(e)
            return JsonResponse({'code': '15', 'errmsg': '数据异常'})
        print("count=", count)
        #   - 3 返回json数据
        return JsonResponse({"count": count, "code": "0", "errmsg": "OK"})


class MobileCountView(View):
    """判断手机号是否重复注册"""

    def get(self, request, mobile):
        """
        :param request: 请求对象
        :param mobile: 手机号
        :return: JSON
        """
        count = User.objects.filter(mobile=mobile).count()
        return JsonResponse({'code': 0, 'errmsg': 'OK', 'count': count})


# 注册视图
class RegisterView(View):
    """用户注册"""

    def post(self, request):
        """
        实现用户注册
        :param request: 请求对象
        :return: 注册结果
        """
        # 1接收数据 获取到json数据
        json_bytes = request.body  # 从请求体中获取原始的JSON数据，bytes类型的
        json_str = json_bytes.decode()  # 将bytes类型的数据转成JSON字符串
        json_dict = json.loads(json_str)  # 将JSON字符串，转成python的标准字典
        # json_dict = json.loads(request.body.decode())
        # 提取参数
        username = json_dict.get('username')
        password = json_dict.get('password')
        password2 = json_dict.get('password2')
        mobile = json_dict.get('mobile')
        allow = json_dict.get('allow')
        sms_code = json_dict.get('sms_code')
        # 2 验证数据 （数据不能为空 数据正则的验证）
        # 判断是否为空
        if not all([username, password, password2, mobile, allow, sms_code]):
            return JsonResponse({'code': 400, 'errmsg': '数据上传错误'})
        # 判断用户名是否是5-20个字符
        if not re.match(r'^[a-zA-Z0-9_]{5,20}$', username):
            return http.JsonResponse({'code': 400, 'errmsg': 'username格式有误!'})
        # 判断密码是否是8-20个数字
        if not re.match(r'^[0-9A-Za-z]{8,20}$', password):
            return http.JsonResponse({'code': 400, 'errmsg': 'password格式有误!'})
        # 判断两次密码是否一致
        if password != password2:
            return http.JsonResponse({'code': 400, 'errmsg': '两次输入不对!'})
        # 判断手机号是否合法
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return http.JsonResponse({'code': 400, 'errmsg': 'mobile格式有误!'})
        # 判断是否勾选用户协议
        if allow != True:
            return http.JsonResponse({'code': 400, 'errmsg': 'allow格式有误!'})
        # 判断验证码是否正确
        # 从redis取验证码
        redis: Redis = get_redis_connection('code')
        sms_code_redis = redis.get('smscode_%s' % mobile)
        # 如果没取到说明到期了
        if not sms_code_redis:
            return JsonResponse({'code': 400, 'errmsg': '验证码过期'})
        # 和用户发过来的对比
        sms_code_redis = sms_code_redis.decode()
        if sms_code != sms_code_redis:
            return JsonResponse({'code': 400, 'errmsg': '验证码输入错误'})

        try:
            user = User.objects.create_user(username=username, password=password, mobile=mobile)
        except Exception as e:
            print(e)
            return JsonResponse({'code': 400, 'errmsg': '注册失败'})
        # 把用户信息保存到session
        login(request, user)
        response = JsonResponse({'code': '0', 'errmsg': 'ok'})
        response.set_cookie('username',user.username,max_age=3600*24*15)
        # 2.4 返回响应
        return response


# 登录
class LoginView(View):
    def post(self, request):
        body = request.body
        data_dict = json.loads(body)
        username = data_dict.get('username')
        password = data_dict.get('password')
        remembered = data_dict.get('remembered')
        # 多账号登录
        if re.match('^1[3-9]\d{9}$', username):
            # 手机号
            User.USERNAME_FIELD = 'mobile'
        else:
            # 用户名
            # 根据用户名数据库取user 对象返回
            User.USERNAME_FIELD = 'username'
        # 2 验证数据是否为空  正则
        if not all([username, password]):
            return JsonResponse({'code': 400, 'errmsg': '写错了'})
        # 3 验证码用户名和密码是否正确
        user = authenticate(username=username, password=password)
        if not user:
            return JsonResponse({'code': 400, 'errmsg': '用户名密码错误'})
        # 4 状态保持
        login(request, user)
        # 5 判断是否记住登录
        if remembered:
            # 如果记住:  设置为两周有效
            request.session.set_expiry(None)
        else:
            # 如果没有记住: 关闭立刻失效
            request.session.set_expiry(0)

        # 6 返回响应
        response = JsonResponse({'code': 0, 'errmsg': 'ok'})
        # 注册时用户名写入到cookie，有效期15天
        response.set_cookie('username', user.username, max_age=3600 * 24 * 15)

        return response



# 退出登录
class LogoutView(View):

    def delete(self, request):
        """实现退出登录逻辑"""
        # 清理session
        logout(request)
        # 退出登录，重定向到登录页
        response = JsonResponse({'code': 0, 'errmsg': 'ok'})
        # 退出登录时清除cookie中的username
        response.delete_cookie('username')

        return response

#LoginRequiredJSONMixin
#如果用用户登录，那么正常执行视图里面的函数
#如果没有登录视图根本不执行
class UserInfoView(LoginRequiredJSONMixin,View):
    def get(self, request):
        # 1取出session里的数据  数据里有用户信息
        # 4 如果登录了 返回 用户名  手机号  邮箱  邮箱是否激活
        return JsonResponse({'code': 0, 'errmsg': 'ok','info_data':{
            'username':request.user.username,
            'mobile':request.user.mobile,
            "email": request.user.email,
            "email_active":request.user.email_active
        }})


class SaveEmailView(View):
    def put(self,request):
        #1.获取json数据 转为字典
        body = request.body
        data_dict = json.loads(body)
        #2 从字典里拿到邮箱地址
        email=data_dict.get('email')
        #3校验
        if not email:
            return JsonResponse({'code': 300, 'errmsg':'邮箱不存在'})
        #4保存到数据库
        try:
            request.user.email = email
            request.user.save()
        except Exception as e:
            print(e)
            return JsonResponse({'code': 400, 'errmsg': '邮箱保存失败'})
        #5 返回响应
        #异步发送邮件
        verify_url = generate_verify_email_url(request.user)
        message = '<p>尊敬的用户您好！</p><p>感谢您使用美多商城。</p>' \
                       '<p>您的邮箱为：%s 。请点击此链接激活您的邮箱：</p>' \
                       '<p><a href="%s">点我激活</a></p>' % (email, verify_url,)

        send_email_active.delay(email,message)


        return JsonResponse({'code': 0, 'errmsg': 'ok'})


class EmailVerifyView(View):
    def put(self,request):
        # 1接受请求
        #2获取token
        token = request.GET.get('token')
        #3对token解密 获取解密数据里的user_id
        user_id = check_verify_email_token(token)
        # - 5 如果获取不到 说明过期
        if not user_id:
            return JsonResponse({'code': 400, 'errmsg': '激活邮件已经过期'})
        # - 6 根据user_id去数据库查询
        try:
            user = User.objects.get(id=user_id)
            print(user)
        except Exception as e:
            print(e)
            return JsonResponse({'code': 405, 'errmsg': '当前用户不存在'})
        # - 7 把查到user对象的 email_active字段 改为true  不要忘记save
        user.email_active = True
        user.save()
        return JsonResponse({'code': 0, 'errmsg': '激活成功'})
